/*
 * Copyright 2010 Aekold Helbrass
 * 
 * This file is part of RosterComposer.
 * 
 * RosterComposer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * RosterComposer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with RosterComposer.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.heresylabs.rostercomposer;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.List;
import org.heresylabs.rostercomposer.roster.RosterEntry;
import org.heresylabs.rostercomposer.units.Option;

/**
 *
 * @author Aekold Helbrass <Helbrass@gmail.com>
 */
public class OptionsGroup extends OptionComponent {

    private OptionComponent[] group;
    private final OptionCheck thisOptionCheck;

    public OptionsGroup(RosterEntry rosterEntry, Option thisOption) {
        super(rosterEntry, thisOption);
        super.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.weighty = 0.5;
        thisOptionCheck = new OptionCheck(rosterEntry, getOption());
        thisOptionCheck.addOptionListener(new OptionListener() {

            @Override
            public void fireOptionChanged(Option option, boolean selected) {
                if (!selected) {
                    deselect();
                }
                else {
                    uncheckFreeEmptyGroup();
                }
                OptionsGroup.this.fireOptionChanged(selected);
            }

        });
        super.add(thisOptionCheck, c);
        c.insets = new Insets(0, 22, 0, 0);
        List<Option> options = getOption().getOptions();
        if (options != null && options.size() > 0) {
            OptionListener optionListener = new OptionListener() {

                @Override
                public void fireOptionChanged(Option option, boolean selected) {
                    subOptionChanged(option, selected);
                }

            };
            group = new OptionComponent[options.size()];
            for (int i = 0; i < options.size(); i++) {
                c.gridy = i + 1;
                Option option = options.get(i);
                OptionComponent component;
                component = OptionComponent.createOptionComponent(rosterEntry, option);
                component.addOptionListener(optionListener);
                group[i] = component;
                super.add(component, c);
            }
        }
        super.setMaximumSize(new Dimension(super.getMaximumSize().width, super.getPreferredSize().height));
        super.setToolTipText(composeTooltip());
        checkEnabled();
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (isEnabled() == enabled) {
            return;
        }
        super.setEnabled(enabled);
        thisOptionCheck.setEnabled(enabled);
        if (group != null && group.length > 0) {
            for (int i = 0; i < group.length; i++) {
                group[i].setEnabled(enabled);
            }
        }
    }

    private void subOptionChanged(Option option, boolean selected) {
        if (selected) {
            if (thisOptionCheck != null) {
                thisOptionCheck.select();
            }
            // if isOne - we should disable any other enabled options:
            if (getOption().isOne()) {
                if (group != null && group.length > 0) {
                    for (int i = 0; i < group.length; i++) {
                        OptionComponent optionComponent = group[i];
                        if (optionComponent.getOption() != option) {
                            optionComponent.deselect();
                        }
                    }
                }
            }
            // we must be selected if any child option is selected:
            fireOptionChanged(true);
        }
        else {
            // if current option is free - just uncheck the box:
            uncheckFreeEmptyGroup();
        }
    }

    private void uncheckFreeEmptyGroup() {
        if (getOption().isFree()) {
            int numberSelected = 0;
            if (group != null && group.length > 0) {
                for (int i = 0; i < group.length; i++) {
                    OptionComponent optionComponent = group[i];
                    if (getRosterEntry().hasOption(optionComponent.getOption())) {
                        numberSelected++;
                    }
                }
            }
            if (numberSelected == 0) {
                thisOptionCheck.deselect();
            }
        }
    }

    @Override
    public void select() {
        if (thisOptionCheck != null) {
            thisOptionCheck.select();
        }
    }

    @Override
    public void deselect() {
        if (thisOptionCheck != null) {
            thisOptionCheck.deselect();
        }
        if (group != null && group.length > 0) {
            for (int i = 0; i < group.length; i++) {
                OptionComponent optionComponent = group[i];
                optionComponent.deselect();
            }
        }
    }

}
